package com.example.modulepicselector.view.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
import com.example.modulepicselector.R;
import static android.graphics.Color.BLUE;
import static android.graphics.Color.WHITE;


public class CheckView extends View {
    private static final int SIZE = 48; // dp
    private static final int CONTENT_SIZE = 16; // dp
    private static final float STROKE_WIDTH = 3.0f; // dp
    private static final float STROKE_RADIUS = 11.5f; // dp
    private static final float BG_RADIUS = 11.0f; // dp
    private static final int UNCHECKED = Integer.MIN_VALUE;
    private boolean mCountable;
    private int mCheckedNum;
    private float mDensity;
    private TextPaint mTextPaint;
    private Paint mStrokePaint;
    private Paint mBackgroundPaint;
    private boolean mChecked;
    private Rect mCheckRect;
    private Drawable mCheckDrawable;
    private boolean mEnabled = true;


    private boolean mIsSelected;


    public boolean isIsSelected() {
        return mIsSelected;
    }

    public void setIsSelected(boolean mIsSelected) {
        this.mIsSelected = mIsSelected;
    }

    public CheckView(Context context) {
        super(context);
        init(context);
    }



    public CheckView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
        
    }
    
    public CheckView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mDensity = context.getResources().getDisplayMetrics().density;
        mStrokePaint = new Paint();
        mStrokePaint.setAntiAlias(true);
        mStrokePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
        mStrokePaint.setStrokeWidth(STROKE_WIDTH * mDensity);
        mStrokePaint.setColor(WHITE);

        mCheckDrawable = ResourcesCompat.getDrawable(context.getResources(),
                R.drawable.ic_check_white_18dp, context.getTheme());
    }



    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // fixed size 48dp x 48dp
        int sizeSpec = MeasureSpec.makeMeasureSpec((int) (SIZE * mDensity), MeasureSpec.EXACTLY);
        super.onMeasure(sizeSpec, sizeSpec);
    }

    public void setChecked(boolean checked) {
        if (mCountable) {
            throw new IllegalStateException("選擇是可數的，不應該setCheck");
        }
        mChecked = checked;
        invalidate();
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);


        // draw white stroke
        canvas.drawCircle((float) SIZE * mDensity / 2, (float) SIZE * mDensity / 2,
                STROKE_RADIUS * mDensity, mStrokePaint);

        if (mIsSelected) {
            // draw content
            if (mCountable) {
                if (mCheckedNum != UNCHECKED) {

                    initBackgroundPaint();
                    if (mCheckedNum < 0) {
                        mBackgroundPaint.setColor(WHITE);
                    }
                    canvas.drawCircle((float) SIZE * mDensity / 2, (float) SIZE * mDensity / 2,
                            BG_RADIUS * mDensity, mBackgroundPaint);
                    initTextPaint();
                    String text = String.valueOf(mCheckedNum);
                    int baseX = (int) (canvas.getWidth() - mTextPaint.measureText(text)) / 2;
                    int baseY = (int) (canvas.getHeight() - mTextPaint.descent() - mTextPaint.ascent()) / 2;
                    canvas.drawText(text, baseX, baseY, mTextPaint);
                }
            } else {
                if (mChecked) {
                    initBackgroundPaint();
                    canvas.drawCircle((float) SIZE * mDensity / 2, (float) SIZE * mDensity / 2,
                            BG_RADIUS * mDensity, mBackgroundPaint);

                    mCheckDrawable.setBounds(getCheckRect());
                    mCheckDrawable.draw(canvas);
                }
            }
        }

        // enable hint
        setAlpha(mEnabled ? 1.0f : 0.5f);
    }



    public void setEnabled(boolean enabled) {
        if (mEnabled != enabled) {
            mEnabled = enabled;
            invalidate();
        }
    }

    private void initBackgroundPaint() {
        if (mBackgroundPaint == null) {
            mBackgroundPaint = new Paint();
            mBackgroundPaint.setAntiAlias(true);
            mBackgroundPaint.setStyle(Paint.Style.FILL);
            mBackgroundPaint.setColor(BLUE);
        }
    }

    private void initTextPaint() {
        if (mTextPaint == null) {
            mTextPaint = new TextPaint();
            mTextPaint.setAntiAlias(true);
            mTextPaint.setColor(Color.WHITE);
            mTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
            mTextPaint.setTextSize(12.0f * mDensity);
        }
        invalidate();
    }

    public void setCountable(boolean countable) {
        mCountable = countable;
    }

    public void setCheckedNum(int checkedNum) {
        if (!mCountable) {
            throw new IllegalStateException("检查视图不可数，请调用 setchecked ()。\n" );
        }
        if (checkedNum != UNCHECKED && checkedNum <= 0) {
            throw new IllegalArgumentException("检查过了 num 不能是阴性的。\n" +
                    "\n");
        }
        mCheckedNum = checkedNum;
        invalidate();
    }

    private Rect getCheckRect() {
        if (mCheckRect == null) {
            int rectPadding = (int) (SIZE * mDensity / 2 - CONTENT_SIZE * mDensity / 2);
            mCheckRect = new Rect(rectPadding, rectPadding,
                    (int) (SIZE * mDensity - rectPadding), (int) (SIZE * mDensity - rectPadding));
        }

        return mCheckRect;
    }


}
